import { BasicColumn, FormSchema } from '@/components/Table';
import { ComponentType } from '@/components/Form/src/types/index';
import { AnField } from '@/api/sys/model/entitysModel';
import { getDict, toJSON, uploadApi } from "@/api/sys/anno";
import { isEmpty } from '@/utils/is';
import { getColumns } from '@/utils/anno/AnnoTableUtils';
import { DescItem } from '@/components/Description';

const SearchFormItemDict: Record<string, ComponentType> = {
  STRING: 'Input',
  LINK: 'Input',
  NUMBER: 'InputNumber',
  DATE: 'DatePicker',
  DATETIME: 'DatePicker',
  OPTIONS: 'ApiSelect',
  PICKER: 'ApiSelect',
  TREE: 'ApiTreeSelect',
  RADIO: 'ApiSelect',
  QR_CODE: 'Input',
  TEXT_AREA: 'Input',
  MarkDown: 'Input',
  CLASS_OPTIONS: 'ExpertInput',
};
const EditFormItemDict: Record<string, ComponentType> = {
  STRING: 'Input',
  NUMBER: 'InputNumber',
  FILE: 'Upload',
  DATE: 'DatePicker',
  DATETIME: 'DatePicker',
  OPTIONS: 'ApiSelect',
  PICKER: 'ApiSelect',
  TREE: 'ApiTreeSelect',
  IMAGE: 'ImageUpload',
  AVATAR: 'CropperAvatar',
  ICON: 'IconPicker',
  RICH_TEXT: 'Tinymce',
  CODE_EDITOR: 'CodeEditor',
  RADIO: 'ApiRadioGroup',
  COLOR: 'ColorPicker',
  LINK: 'Input',
  QR_CODE: 'Input',
  TEXT_AREA: 'InputTextArea',
  MARK_DOWN: 'MarkDown',
  CLASS_OPTIONS: 'ExpertInput',
};

const fieldsName = { resultfield: 'data', labelfield: 'label', valuefield: 'value' };
const labelAlign = 'left';
//字典增加Key值
const formatterDictKey = (dict: any[]) => {
  if (!dict) {
    return [];
  }
  return dict.map((item) => {
    let label = item.label;
    if (label instanceof Object) {
      label = label.value || toJSON(label);
    }
    return {
      label: label,
      value: (item.value || item.id).toString(),
      key: item.value || item.id,
      children: formatterDictKey(item.children),
    };
  });
};

//获取可增加的form字段
export function getAnnoAddForm(fieldsDatas: AnField[]): FormSchema[] {
  const fields = fieldsDatas.filter(
    (item) => item.edit.addEnable && EditFormItemDict[item.dataType],
  );
  // @ts-ignore
  return getFields(fields, 'add');
}
//获取可编辑的form字段
export function getAnnoEditForm(fieldsDatas: AnField[]): FormSchema[] {
  const fields = fieldsDatas.filter(
    (item) => item.edit.editEnable && EditFormItemDict[item.dataType],
  );
  // @ts-ignore
  return getFields(fields, 'edit');
}
// 查询描述字段【详情页】
export function getAnnoDescriptionForm(fieldsDatas: AnField[]): Array<DescItem> {
  const columns: BasicColumn[] = getColumns(fieldsDatas);
  return columns.map((item) => {
    return {
      label: item.title,
      field: item.dataIndex,
      span: getDescriptionCmpSpan(item),
      render: (curVal, data: Recordable<any>) => {
        if (item.customRender == undefined) {
          return curVal;
        }
        return item.customRender({
          value: curVal,
          record: data,
          column: undefined as any,
          index: undefined as any,
          renderIndex: undefined as any,
          text: undefined as any,
        });
      },
    } as DescItem;
  });
}
//可查询的form字段
export function getAnnoSearchForm(fieldsDatas: AnField[], getIsMobile: any): FormSchema[] {
  if (getIsMobile == undefined) {
    getIsMobile = ref(false);
  }
  const fields = fieldsDatas.filter(
    (item) => item.search.enable && SearchFormItemDict[item.dataType],
  );
  return getFields(fields, 'search', getIsMobile);
}

type formType = 'search' | 'add' | 'edit';
const getFields = (fields: AnField[], type: formType, getIsMobile: any): FormSchema[] => {
  return fields.map((item): FormSchema => {
    return {
      field: item.javaName,
      label: item.title,
      component: getFormItemDict(type, item),
      defaultValue: getDefaultValue(item, type),
      labelWidth: getCmpWidth(item, type),
      colProps: { span: getCmpSpan(item, type, getIsMobile) },
      show: (formData) => {
        if (item.edit?.showBy?.enable) {
          return eval(item.edit?.showBy?.expr?.replace('annoDataForm', 'formData.model'));
        }
        if (type == 'search') {
          return item.search?.enable && SearchFormItemDict[item.dataType];
        }
        return true;
      },
      required: type == 'search' ? item.search?.notNull : item.edit?.notNull,
      ...getDictComponentProps(item, type),
    };
  });
};

function getFormItemDict(type: formType, item: AnField) {
  return type == 'search' ? SearchFormItemDict[item.dataType] : EditFormItemDict[item.dataType];
}

const getDefaultValue = (item: AnField, type: formType) => {
  if (type == 'search') {
    const defaultValue = item.search?.defaultValue == '' ? undefined : item.search.defaultValue;
    return defaultValue;
  }
};
const getCmpWidth = (item: AnField, type: formType) => {
  if (item.title.length > 6) {
    return 'auto';
  }
  return 100;
};
const getDescriptionCmpSpan = (item: BasicColumn) => {
  let span = 1;
  if (
    ['IMAGE', 'FILE', 'CODE_EDITOR', 'RICH_TEXT', 'TEXT_AREA', 'AVATAR', 'MARK_DOWN'].includes(
      item['annoType'],
    )
  ) {
    span = 3;
  }
  return span;
};

const getCmpSpan = (item: AnField, type: formType, getIsMobile: any) => {
  let span = 12;
  if (type == 'search') {
    if (getIsMobile.value) {
      span = 12;
    } else {
      span = 8;
    }
  }
  if (
    ['IMAGE', 'FILE', 'CODE_EDITOR', 'RICH_TEXT', 'TEXT_AREA', 'AVATAR', 'MARK_DOWN'].includes(
      item.dataType,
    )
  ) {
    span = 24;
  }
  if (item.edit.span && type != 'search') {
    span = item.edit.span;
  }
  return span;
};
const getDictComponentProps = (item: AnField, type: formType): Pick<FormSchema, any> => {
  let showTime: boolean | unknown = null;
  let valueFormat: String | unknown = null;
  switch (item.dataType) {
    case 'DATE':
      showTime = false;
      valueFormat = 'YYYY-MM-DD';
      break;
    case 'DATETIME':
      showTime = true;
      valueFormat = 'YYYY-MM-DD HH:mm:ss';
      break;
    default:
      break;
  }
  if (['OPTIONS', 'PICKER', 'TREE', 'RADIO'].includes(item.dataType)) {
    return getPickDictComponentProps(item, type);
  }
  if (['CLASS_OPTIONS'].includes(item.dataType)) {
    return {
      componentProps: {
        api: uploadApi,
        valueKey: item.optionType.optionAnno.idKey,
        labelKey: item.optionType.optionAnno.labelKey,
        annoClass: item.optionType.optionAnno.annoClass,
      },
    };
  }
  if ('COLOR' === item.dataType) {
    return {
      defaultValue: '',
      componentProps: {
        width: 100,
        height: 30,
        showAlpha: true,
      },
    };
  }

  if ('CODE_EDITOR' === item.dataType) {
    return {
      componentProps: {
        cmOptions: {
          mode: item.codeType.mode,
          theme: item.codeType.theme,
          readOnly: false,
          lineNumbers: true,
          lineWiseCopyCut: true,
          gutters: ['CodeMirror-lint-markers'],
          lint: true,
        },
        height: '300px',
      },
    };
  }
  if (['IMAGE', 'FILE', 'AVATAR'].includes(item.dataType)) {
    if (item.dataType == 'IMAGE') {
      return {
        componentProps: {
          api: uploadApi,
          accept: ['png', 'jpeg', 'jpg'],
          maxNumber: 1,
        },
      };
    } else if (item.dataType == 'FILE') {
      const accepts = item.fileType.fileType.split(',');
      const returnProps = {
        api: uploadApi,
        maxNumber: item.fileType.fileMaxCount,
        maxSize: item.fileType.fileMaxSize,
      };
      if (!(accepts.length == 1 && accepts[0] == '*')) {
        returnProps['accept'] = accepts;
      }
      return {
        componentProps: returnProps,
      };
    } else if (item.dataType == 'AVATAR') {
      return {
        componentProps: {
          uploadApi: uploadApi,
          width: '100px',
        },
      };
    }
  }

  return {
    componentProps: {
      showTime,
      valueFormat,
      labelAlign,
      placeholder: item[`${type}PlaceHolder`],
    },
  };
};

const getPickDictComponentProps = (
  item: AnField,
  type: formType,
): Pick<FormSchema, 'componentProps'> => {
  let api: any = null;
  let options: any = null;
  let multi: boolean | unknown = null;
  if (item.optionType.value && !isEmpty(item.optionType.value)) {
    options = formatterDictKey(item.optionType.value);
    multi = item.optionType.isMultiple;
  } else if (item.treeType.value && !isEmpty(item.treeType.value)) {
    options = formatterDictKey(item.treeType.value);
    multi = item.treeType.isMultiple;
  } else if (item.optionType.sqlKey) {
    api = () => getDict({ sqlKey: item.optionType.sqlKey });
    multi = item.optionType.isMultiple;
  } else if (item.optionType.supplier && item.optionType.supplier != 'OptionDataSupplier') {
    api = () => getDict({ optionAnnoClazz: item.optionType.supplier });
    multi = item.optionType.isMultiple;
  } else if (item.treeType.sqlKey) {
    api = () => getDict({ sqlKey: item.treeType.sqlKey });
    multi = item.treeType.isMultiple;
  } else if (item.treeType.treeAnno && item.treeType.treeAnno.annoClass != 'Object') {
    api = () => getDict({ ...item.treeType.treeAnno, annoClazz: item.treeType.treeAnno.annoClass });
    multi = item.treeType.isMultiple;
  } else if (item.treeType.supplier && item.treeType.supplier != 'TreeDataSupplier') {
    api = () => getDict({ treeAnnoClazz: item.treeType.supplier });
    multi = item.treeType.isMultiple;
  } else if (item.optionType.optionAnno && item.optionType.optionAnno.annoClass != 'Object') {
    api = () =>
      getDict({ ...item.optionType.optionAnno, annoClazz: item.optionType.optionAnno.annoClass });
    multi = item.optionType.isMultiple;
  } else if (item.treeType.onlineDictKey) {
    api = () => getDict({ onlineDictKey: item.treeType.onlineDictKey });
  } else if (item.optionType.onlineDictKey) {
    api = () => getDict({ onlineDictKey: item.optionType.onlineDictKey });
  }
  const res = {
    componentProps: {
      placeholder: item[`${type}PlaceHolder`],
      ...fieldsName,
      immediate: true,
      multiple: multi,
      showCheckedStrategy: multi ? 'SHOW_ALL' : null,
      mode: multi ? 'multiple' : null,
    },
  };
  if (api) {
    res.componentProps['api'] = api;
  }
  if (options) {
    res.componentProps['options'] = options;
  }
  return res;
};
